﻿using System;
using System.Collections.Generic;
using NHibernate.Criterion;
using Rhino.Commons;

namespace NoMiddleman.Data
{
    public class BaseRepository<T> : Core.DataInterfaces.IRepository<T>
    {
        public T Get(int id)
        {
            return Repository<T>.Get(id);
        }

        public T Load(int id)
        {
            return Repository<T>.Load(id);
        }

        public ICollection<T> GetAll()
        {
            return Repository<T>.FindAll();
        }

        public ICollection<T> GetByExample(T exampleInstance, params string[] propertiesToExclude)
        {
            DetachedCriteria criteria = Repository<T>.CreateDetachedCriteria();
            Example example = Example.Create(exampleInstance);

            foreach (string propertyToExclude in propertiesToExclude)
            {
                example.ExcludeProperty(propertyToExclude);
            }

            criteria.Add(example);

            return Repository<T>.FindAll(criteria);
        }

        public ICollection<T> GetByProperties(IDictionary<string, object> propertyValuePairs)
        {
            if(propertyValuePairs == null || propertyValuePairs.Count == 0)
                throw new ArgumentException(
                "propertyValuePairs was null or empty; " +
                "it has to have at least one property/value pair in it");

            DetachedCriteria criteria = Repository<T>.CreateDetachedCriteria();

            foreach (string key in propertyValuePairs.Keys)
            {
                criteria.Add(Expression.Eq(key, propertyValuePairs[key]));
            }

            return Repository<T>.FindAll(criteria);
        }

        public T Save(T entity)
        {
            return Repository<T>.Save(entity);
        }

        public T Update(T entity)
        {
            Repository<T>.Update(entity);
            return entity;
        }

        public void Delete(T entity)
        {
            Repository<T>.Delete(entity);
        }

        public T SaveOrUpdate(T entity)
        {
            return Repository<T>.SaveOrUpdate(entity);
        }
    }
}
